﻿using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Timtopia.DGMLPosterView;
using Microsoft.VisualStudio.GraphModel;
using System.Collections.Generic;

namespace ParserTest
{
    [TestClass]
    public class ParserTest
    {
        [TestMethod]
        public void MatchBrackets1()
        {
            string s = "()";
            int start, length;
            Parser.FindFirstMatchingBrackets(s, out start, out length);
            Assert.AreEqual(1, start);
            Assert.AreEqual(0, length);
        }
        [TestMethod]
        public void MatchBrackets2()
        {
            string s = "(())";
            int start, length;
            Parser.FindFirstMatchingBrackets(s, out start, out length);
            Assert.AreEqual(1, start);
            Assert.AreEqual(2, length);
        }
        [TestMethod]
        public void MatchBrackets3()
        {
            string s = ")(())";
            int start, length;
            Parser.FindFirstMatchingBrackets(s, out start, out length);
            Assert.AreEqual(2, start);
            Assert.AreEqual(2, length);
        }
        [TestMethod]
        public void MatchBrackets4()
        {
            string s = "blah (asdjfkl ( jaskdf ) ; asdf ( sdjf ) ;asdjkfl())asdf";
            int start, length;
            Parser.FindFirstMatchingBrackets(s, out start, out length);
            Console.WriteLine(s.Substring(start, length));
            Assert.AreEqual(6, start);
            Assert.AreEqual(45, length);
        }

        [TestMethod]
        public void CommonPrefix()
        {
            string[] strings = new string[] {
                "timwashere",
                "timisawesome",
                "timrocks"
            };
            Assert.AreEqual("tim", Parser.CommonPrefix(strings));
        }

        [TestMethod]
        public void ParseNode()
        {
            const string TestTree = "primitive[gabd|ceh|f](linear[gh|f]([g];complete_0[hf]([h];[f]));[a];[b];complete_1[cd]([c];[d]);[e])";
            Node root = Parser.ParseNode(TestTree);
            Parser.PrintTree(root, 0);
            Assert.AreEqual(5, root.Children.Count);
            Assert.AreEqual(2, root.Children[0].Children.Count);
            Assert.AreEqual("g", root.Children[0].Children[0].Label);
            Assert.AreEqual(2, root.Children[0].Children[1].Children.Count);
            Assert.AreEqual("h", root.Children[0].Children[1].Children[0].Label);
            Assert.AreEqual("f", root.Children[0].Children[1].Children[1].Label);
            Assert.AreEqual("a", root.Children[1].Label);
            Assert.AreEqual("b", root.Children[2].Label);
            Assert.AreEqual(2, root.Children[3].Children.Count);
            Assert.AreEqual("c", root.Children[3].Children[0].Label);
            Assert.AreEqual("d", root.Children[3].Children[1].Label);
            Assert.AreEqual("e", root.Children[4].Label);
        }

        [TestMethod]
        public void PhraseNetsDecompositionOutgoing()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            g.Nodes.GetOrCreate("c");
            g.Links.GetOrCreate("a", "c");
            g.Links.GetOrCreate("b", "c");
            PhrasenetsDecomposition.Apply(g);
            Assert.AreEqual(1, g.Groups.Count);
            var children = g.Groups.GetGroups().First().ChildNodes;
            Assert.AreEqual(2, children.Count);
            Assert.IsTrue(children.Contains(a));
            Assert.IsTrue(children.Contains(b));
        }

        [TestMethod]
        public void PhraseNetsDecompositionIncoming()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            g.Nodes.GetOrCreate("c");
            g.Links.GetOrCreate("c", "a");
            g.Links.GetOrCreate("c", "b");
            PhrasenetsDecomposition.Apply(g);
            Assert.AreEqual(1, g.Groups.Count);
            var children = g.Groups.GetGroups().First().ChildNodes;
            Assert.AreEqual(2, children.Count);
            Assert.IsTrue(children.Contains(a));
            Assert.IsTrue(children.Contains(b));
        }

        [TestMethod]
        public void PhraseNetsDecompositionBidirectional()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            g.Nodes.GetOrCreate("c");
            g.Links.GetOrCreate("a", "c");
            g.Links.GetOrCreate("b", "c");
            g.Links.GetOrCreate("c", "a");
            g.Links.GetOrCreate("c", "b");
            PhrasenetsDecomposition.Apply(g);
            Assert.AreEqual(1, g.Groups.Count);
            var children = g.Groups.GetGroups().First().ChildNodes;
            Assert.AreEqual(2, children.Count);
            Assert.IsTrue(children.Contains(a));
            Assert.IsTrue(children.Contains(b));
        }

        [TestMethod]
        public void PhraseNetsDecompositionComplete()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            var c = g.Nodes.GetOrCreate("c");
            g.Nodes.GetOrCreate("d");
            g.Links.GetOrCreate("a", "b");
            g.Links.GetOrCreate("b", "a");
            g.Links.GetOrCreate("a", "c");
            g.Links.GetOrCreate("c", "a");
            g.Links.GetOrCreate("b", "c");
            g.Links.GetOrCreate("c", "b");
            g.Links.GetOrCreate("c", "d");
            PhrasenetsDecomposition.Apply(g);
            Assert.AreEqual(1, g.Groups.Count);
            var children = g.Groups.GetGroups().First().ChildNodes;
            Assert.AreEqual(2, children.Count);
            Assert.IsTrue(children.Contains(a));
            Assert.IsTrue(children.Contains(b));
        }

        [TestMethod]
        public void ShortestPathsFloydWarshall()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            var c = g.Nodes.GetOrCreate("c");
            g.Links.GetOrCreate("a", "b");
            g.Links.GetOrCreate("b", "c");
            List<GraphNode> V;
            var d = Timtopia.DGMLPosterView.ShortestPaths.FloydWarshall(g, out V);
            int n = g.Nodes.Count;
            Assert.AreEqual(n * n, d.Length);
            for (int i = 0; i < n; ++i)
            {
                Assert.AreEqual(0, d[i, i]);
            }
            Assert.AreEqual(1, d[0, 1]);
            Assert.AreEqual(1, d[1, 2]);
            Assert.AreEqual(2, d[0, 2]);
            Assert.AreEqual(-1, d[1, 0]);
            Assert.AreEqual(-1, d[2, 1]);
            Assert.AreEqual(-1, d[2, 0]);
        }

        [TestMethod]
        public void ShortestPath()
        {
            Graph g = new Graph();
            var a = g.Nodes.GetOrCreate("a");
            var b = g.Nodes.GetOrCreate("b");
            var c = g.Nodes.GetOrCreate("c");
            var d = g.Nodes.GetOrCreate("d");
            var e = g.Nodes.GetOrCreate("e");
            g.Links.GetOrCreate("a", "b");
            g.Links.GetOrCreate("b", "c");
            g.Links.GetOrCreate("b", "d");
            var ad = g.Links.GetOrCreate("a", "d");
            var de = g.Links.GetOrCreate("d", "e");
            List<GraphLink> paths;
            int dist = Timtopia.DGMLPosterView.ShortestPaths.FromTo(a, e, out paths);
            Assert.AreEqual(2, dist);
            Assert.AreEqual(2, paths.Count);
            Assert.IsTrue(paths.Contains(ad));
            Assert.IsTrue(paths.Contains(de));

            var ac = g.Links.GetOrCreate("a", "c");
            var ce = g.Links.GetOrCreate("c", "e");

            dist = Timtopia.DGMLPosterView.ShortestPaths.FromTo(a, e, out paths);
            Assert.AreEqual(2, dist);
            Assert.AreEqual(4, paths.Count);
            Assert.IsTrue(paths.Contains(ad));
            Assert.IsTrue(paths.Contains(de));
            Assert.IsTrue(paths.Contains(ac));
            Assert.IsTrue(paths.Contains(ce));
        }
    }
}

